`timescale 1ns / 1ps
`include "const_def.vh"

module data_mem(
        //input
        input           clk,
        input [11:2]    mem_addr,
        input [31:0]    mem_wdata,

        //ctrl signal
        input           ctrl_mem_wM,
        input   [1:0]   ctrl_bhwM,

        //output
        output [31:0]   mem_rdata

    );

    reg [7:0]   data_memory[31:0];

    initial begin
        $readmemh("C:/Users/95135/Desktop/tests/data_memory.txt",data_memory);
    end

    always @(posedge clk) begin
        if (ctrl_mem_wM) begin
            case (ctrl_bhwM)
                `TYPE_WORD: begin
                    data_memory[mem_addr+3] <= mem_wdata[31:24];
                    data_memory[mem_addr+2] <= mem_wdata[23:16];
                    data_memory[mem_addr+1] <= mem_wdata[15:8];
                    data_memory[mem_addr] <= mem_wdata[7:0];
                end
                `TYPE_HALFWORD: begin
                    data_memory[mem_addr+1] <= mem_wdata[15:8];
                    data_memory[mem_addr] <= mem_wdata[7:0];
                end
                `TYPE_BYTE: begin
                    data_memory[mem_addr] <= mem_wdata[7:0];
                end
                default: begin
                end
            endcase
        end
    end

    wire    [31:0]  mem_rdata32 ;
    wire    [31:0]  mem_rdata16 ;
    wire    [31:0]  mem_rdata8;

    wire    [7:0]   mem_rdata16_sign = data_memory[mem_addr+1];
    wire    [7:0]   mem_rdata8_sign = data_memory[mem_addr];

    assign  mem_rdata32 = {
                data_memory[mem_addr+3],
                data_memory[mem_addr+2],
                data_memory[mem_addr+1],
                data_memory[mem_addr]
            };
    assign  mem_rdata16 = {
                {16{mem_rdata16_sign[7]}},
                data_memory[mem_addr+1],
                data_memory[mem_addr]
            };
    assign  mem_rdata8 = {
                {24{mem_rdata8_sign[7]}},
                data_memory[mem_addr]
            };

    assign  mem_rdata = (ctrl_bhwM == `TYPE_WORD) ? mem_rdata32 : (
                (ctrl_bhwM == `TYPE_HALFWORD) ? mem_rdata16 : (
                    (ctrl_bhwM == `TYPE_BYTE) ? mem_rdata8 : 32'b0
                )
            );
endmodule

